const crypto = require('crypto')
const cache = require('memory-cache')

module.exports = (app) => {
  // 定义collection，用于存储session
  const mongoose = app.mongoose
  const exec = mongoose.Query.prototype.exec // 重写 exec 方法，处理缓存逻辑

  mongoose.Query.prototype.cache = function (...args) {
    let options = {}

    if (typeof args[0] === 'object') options = args[0]
    else if (typeof args[0] == Number) {
      options.ttl = args[0]
      options.key = args[1]
    } else if (typeof args[0] === 'string') {
      options.key = args[0]
      options.ttl = args[1]
    }

    this._cache = true
    this._cacheTTL = options.ttl || 60 // 缓存过期时间（默认 60 秒）
    this._cacheKey = options.key // 自定义前缀

    return this
  }

  mongoose.Query.prototype.exec = async function (...args) {
    if (!this._cache) return exec.apply(this, args)

    const query = this.getQuery()
    const collection = this.mongooseCollection.name // 获取集合名称

    const codeText = {
      name: this.model.collection.name,
      conditions: this._conditions,
      fields: this._fields,
      o: this._mongooseOptions,
      distinct: this._distinct,
      op: this.op,
    }

    const hex = md5(JSON.stringify(codeText))

    const cacheKey = `mongoose_cache:${collection}:${this._cacheKey ? this._cacheKey + ':' : ''}${hex}`

    const cachedData = cache.get(cacheKey)

    if (cachedData) {
      const doc = JSON.parse(cachedData)
      return Array.isArray(doc) ? doc.map((d) => new this.model(d)) : new this.model(doc)
    }

    const result = await exec.apply(this, args)

    if (result) {
      cache.put(cacheKey, JSON.stringify(result), this._cacheTTL * 1000)
    }

    return result
  }
}

function md5(str) {
  return crypto.createHash('md5').update(str).digest('hex')
}
